import java.util.Date;
import java.util.List;
import java.util.Scanner;

public class CinemaManagementSystem {
    private User currentUser;
    private SalesReport salesReport = new SalesReport();

    public CinemaManagementSystem() {
        // 初始化数据库连接
        DBUtil.getConnection();
    }

    public void start() {
        Scanner scanner = new Scanner(System.in);
        try {
            while (true) {
                if (currentUser == null) {
                    showLoginMenu(scanner);
                } else {
                    if (currentUser instanceof Admin) {
                        showAdminMenu(scanner);
                    } else if (currentUser instanceof Manager) {
                        showManagerMenu(scanner);
                    } else if (currentUser instanceof FrontDesk) {
                        showFrontMenu(scanner);
                    }
                }
            }
        } finally {
            scanner.close();
            DBUtil.closeConnection(); // 退出时关闭数据库连接
        }
    }

    private void showLoginMenu(Scanner scanner) {
        System.out.println("\n=== 影院管理系统 v1.5 ===");
        System.out.println("1. 登录");
        System.out.println("2. 退出");
        System.out.print("请选择: ");
        int choice = getValidInt(scanner, 1, 2);
        if (choice == 1) {
            login(scanner);
        } else {
            System.out.println("感谢使用影院管理系统，再见！");
            System.exit(0);
        }
    }

    private void login(Scanner scanner) {
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();
        // 密码加密后验证
        String encryptedPwd = MD5Util.encrypt(password);

        User user = UserDAO.getUserByUsername(username);
        if (user != null && user.login(encryptedPwd)) {
            currentUser = user;
            System.out.println("登录成功，欢迎" + user.getUserType() + "[" + username + "]");
        } else {
            System.out.println("用户名或密码错误");
        }
    }

    private void showAdminMenu(Scanner scanner) {
        System.out.println("\n=== 管理员菜单 ===");
        System.out.println("1. 添加用户");
        System.out.println("2. 删除用户");
        System.out.println("3. 重置用户密码");
        System.out.println("4. 查看所有用户");
        System.out.println("5. 退出登录");
        System.out.print("请选择: ");
        int choice = getValidInt(scanner, 1, 5);

        switch (choice) {
            case 1:
                addUser(scanner);
                break;
            case 2:
                deleteUser(scanner);
                break;
            case 3:
                resetPassword(scanner);
                break;
            case 4:
                viewAllUsers();
                break;
            case 5:
                currentUser = null;
                System.out.println("已退出登录");
                break;
        }
    }

    private void addUser(Scanner scanner) {
        System.out.println("\n=== 添加用户 ===");
        System.out.println("1. 添加管理员");
        System.out.println("2. 添加经理");
        System.out.println("3. 添加前台");
        System.out.print("请选择用户类型: ");
        int type = getValidInt(scanner, 1, 3);

        System.out.print("用户ID: ");
        String id = scanner.nextLine();
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();
        // 密码加密处理
        String encryptedPwd = MD5Util.encrypt(password);
        System.out.print("手机号: ");
        String phone = scanner.nextLine();

        User newUser;
        switch (type) {
            case 1:
                newUser = new Admin(id, username, encryptedPwd, phone);
                break;
            case 2:
                newUser = new Manager(id, username, encryptedPwd, phone);
                break;
            case 3:
                newUser = new FrontDesk(id, username, encryptedPwd, phone);
                break;
            default:
                System.out.println("无效的用户类型");
                return;
        }

        try {
            ((Admin) currentUser).addUser(newUser);
            System.out.println("成功添加" + newUser.getUserType() + "[" + username + "]");
        } catch (IllegalArgumentException e) {
            System.out.println("添加失败: " + e.getMessage());
        }
    }

    private void deleteUser(Scanner scanner) {
        System.out.print("\n请输入要删除的用户ID: ");
        String userId = scanner.nextLine();

        try {
            ((Admin) currentUser).deleteUser(userId);
            System.out.println("用户删除成功");
        } catch (IllegalArgumentException e) {
            System.out.println("删除失败: " + e.getMessage());
        }
    }

    private void resetPassword(Scanner scanner) {
        System.out.print("\n请输入要重置密码的用户ID: ");
        String userId = scanner.nextLine();

        User targetUser = UserDAO.getUserById(userId);

        if (targetUser == null) {
            System.out.println("用户不存在");
            return;
        }

        ((Admin) currentUser).resetPassword(targetUser);
        System.out.println("已重置用户[" + targetUser.getUsername() + "]的密码为: 123456");
    }

    private void viewAllUsers() {
        System.out.println("\n=== 所有用户列表 ===");
        List<User> users = UserDAO.getAllUsers();

        if (users.isEmpty()) {
            System.out.println("没有用户记录");
            return;
        }

        System.out.printf("%-10s %-15s %-20s %-10s %-15s%n",
                "ID", "用户名", "手机号", "用户类型", "注册时间");
        System.out.println("--------------------------------------------------------------");

        for (User user : users) {
            System.out.printf("%-10s %-15s %-20s %-10s %-15s%n",
                    user.getId(),
                    user.getUsername(),
                    user.getPhone(),
                    user.getUserType(),
                    user.getRegisterTime());
        }
    }

    private void showManagerMenu(Scanner scanner) {
        System.out.println("\n=== 经理菜单 ===");
        System.out.println("1. 添加电影");
        System.out.println("2. 查看所有电影");
        System.out.println("3. 添加场次");
        System.out.println("4. 修改场次");
        System.out.println("5. 查看所有场次");
        System.out.println("6. 查看销售报表");
        System.out.println("7. 退出登录");
        System.out.print("请选择: ");
        int choice = getValidInt(scanner, 1, 7);

        switch (choice) {
            case 1:
                addMovie(scanner);
                break;
            case 2:
                viewAllMovies();
                break;
            case 3:
                addShow(scanner);
                break;
            case 4:
                updateShow(scanner);
                break;
            case 5:
                viewAllShows();
                break;
            case 6:
                viewSalesReport(scanner);
                break;
            case 7:
                currentUser = null;
                System.out.println("已退出登录");
                break;
        }
    }

    private void addMovie(Scanner scanner) {
        System.out.println("\n=== 添加电影 ===");
        System.out.print("电影ID: ");
        String id = scanner.nextLine();
        System.out.print("电影名称: ");
        String name = scanner.nextLine();
        System.out.print("导演: ");
        String director = scanner.nextLine();
        System.out.print("主演: ");
        String actors = scanner.nextLine();
        System.out.print("简介: ");
        String introduction = scanner.nextLine();
        System.out.print("时长(分钟): ");
        int duration = getValidInt(scanner, 1, 300);
        System.out.print("评分: ");
        double rating = getValidDouble(scanner, 0, 10);

        Movie movie = new Movie(id, name, director, actors, introduction, duration, rating);

        try {
            ((Manager) currentUser).addMovie(movie);
            System.out.println("电影添加成功");
        } catch (RuntimeException e) {
            System.out.println("添加失败: " + e.getMessage());
        }
    }

    private void viewAllMovies() {
        System.out.println("\n=== 所有电影列表 ===");
        List<Movie> movies = MovieDAO.getAllMovies();

        if (movies.isEmpty()) {
            System.out.println("没有电影记录");
            return;
        }

        System.out.printf("%-10s %-20s %-15s %-30s %-10s %-10s%n",
                "ID", "电影名称", "导演", "主演", "时长(分)", "评分");
        System.out.println("------------------------------------------------------------------------------------------------");

        for (Movie movie : movies) {
            System.out.printf("%-10s %-20s %-15s %-30s %-10d %-10.1f%n",
                    movie.getId(),
                    movie.getName(),
                    movie.getDirector(),
                    movie.getActors(),
                    movie.getDuration(),
                    movie.getRating());
        }
    }

    private void addShow(Scanner scanner) {
        System.out.println("\n=== 添加场次 ===");

        // 显示所有电影供选择
        viewAllMovies();
        System.out.print("请输入电影ID: ");
        String movieId = scanner.nextLine();
        Movie movie = MovieDAO.getMovieById(movieId);
        if (movie == null) {
            System.out.println("电影不存在");
            return;
        }

        // 显示所有放映厅供选择
        List<Hall> halls = HallDAO.getAllHalls();
        System.out.println("\n放映厅列表:");
        for (Hall hall : halls) {
            System.out.printf("ID: %s, 名称: %s, 座位: %dx%d%n",
                    hall.getId(), hall.getName(), hall.getRows(), hall.getCols());
        }
        System.out.print("请输入放映厅ID: ");
        String hallId = scanner.nextLine();
        Hall hall = HallDAO.getHallById(hallId);
        if (hall == null) {
            System.out.println("放映厅不存在");
            return;
        }

        System.out.print("场次ID: ");
        String showId = scanner.nextLine();
        System.out.print("放映时间(格式: yyyy-MM-dd HH:mm:ss): ");
        String timeStr = scanner.nextLine();
        Date showTime;
        try {
            showTime = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(timeStr);
        } catch (Exception e) {
            System.out.println("时间格式错误");
            return;
        }
        System.out.print("票价: ");
        double price = getValidDouble(scanner, 0, 500);

        Show show = new Show(showId, movie, hall, showTime, price);

        try {
            ((Manager) currentUser).addShow(show);
            System.out.println("场次添加成功");
        } catch (IllegalArgumentException e) {
            System.out.println("添加失败: " + e.getMessage());
        }
    }

    private void updateShow(Scanner scanner) {
        System.out.println("\n=== 修改场次 ===");

        // 显示所有场次供选择
        viewAllShows();
        System.out.print("请输入要修改的场次ID: ");
        String showId = scanner.nextLine();
        Show show = ShowDAO.getShowById(showId);
        if (show == null) {
            System.out.println("场次不存在");
            return;
        }

        // 选择新电影
        viewAllMovies();
        System.out.print("请输入新的电影ID: ");
        String movieId = scanner.nextLine();
        Movie movie = MovieDAO.getMovieById(movieId);
        if (movie == null) {
            System.out.println("电影不存在");
            return;
        }

        // 选择新放映厅
        List<Hall> halls = HallDAO.getAllHalls();
        System.out.println("\n放映厅列表:");
        for (Hall h : halls) {
            System.out.printf("ID: %s, 名称: %s, 座位: %dx%d%n",
                    h.getId(), h.getName(), h.getRows(), h.getCols());
        }
        System.out.print("请输入新的放映厅ID: ");
        String hallId = scanner.nextLine();
        Hall hall = HallDAO.getHallById(hallId);
        if (hall == null) {
            System.out.println("放映厅不存在");
            return;
        }

        System.out.print("新的放映时间(格式: yyyy-MM-dd HH:mm:ss): ");
        String timeStr = scanner.nextLine();
        Date showTime;
        try {
            showTime = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(timeStr);
        } catch (Exception e) {
            System.out.println("时间格式错误");
            return;
        }
        System.out.print("新的票价: ");
        double price = getValidDouble(scanner, 0, 500);

        // 创建更新后的场次对象
        Show updatedShow = new Show(showId, movie, hall, showTime, price);

        try {
            ((Manager) currentUser).updateShow(updatedShow);
            System.out.println("场次修改成功");
        } catch (IllegalArgumentException e) {
            System.out.println("修改失败: " + e.getMessage());
        }
    }

    private void viewAllShows() {
        System.out.println("\n=== 所有场次列表 ===");
        List<Show> shows = ShowDAO.getAllShows();

        if (shows.isEmpty()) {
            System.out.println("没有场次记录");
            return;
        }

        System.out.printf("%-10s %-20s %-15s %-20s %-10s%n",
                "场次ID", "电影名称", "放映厅", "放映时间", "票价");
        System.out.println("------------------------------------------------------------------");

        for (Show show : shows) {
            System.out.printf("%-10s %-20s %-15s %-20s %-10.2f%n",
                    show.getId(),
                    show.getMovie().getName(),
                    show.getHall().getName(),
                    new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm").format(show.getShowTime()),
                    show.getPrice());
        }
    }

    private void viewSalesReport(Scanner scanner) {
        System.out.println("\n=== 销售报表 ===");
        System.out.println("1. 今日销售报表");
        System.out.println("2. 本周销售报表");
        System.out.println("3. 本月销售报表");
        System.out.println("4. 自定义时间段报表");
        System.out.print("请选择: ");
        int choice = getValidInt(scanner, 1, 4);

        salesReport.generateReport(choice, scanner);
    }

    private void showFrontMenu(Scanner scanner) {
        System.out.println("\n=== 前台菜单 ===");
        System.out.println("1. 查看所有电影");
        System.out.println("2. 查看所有场次");
        System.out.println("3. 售票");
        System.out.println("4. 退票");
        System.out.println("5. 退出登录");
        System.out.print("请选择: ");
        int choice = getValidInt(scanner, 1, 5);

        switch (choice) {
            case 1:
                viewAllMovies();
                break;
            case 2:
                viewAllShows();
                break;
            case 3:
                sellTicket(scanner);
                break;
            case 4:
                refundTicket(scanner);
                break;
            case 5:
                currentUser = null;
                System.out.println("已退出登录");
                break;
        }
    }

    private void sellTicket(Scanner scanner) {
        System.out.println("\n=== 售票 ===");

        // 显示所有场次供选择
        viewAllShows();
        System.out.print("请输入场次ID: ");
        String showId = scanner.nextLine();
        Show show = ShowDAO.getShowById(showId);
        if (show == null) {
            System.out.println("场次不存在");
            return;
        }

        // 显示座位情况
        System.out.println("\n座位情况 (O: 可选, X: 已售):");
        Hall hall = show.getHall();
        List<Seat> seats = hall.getSeats();

        // 打印列号
        System.out.print("   ");
        for (int i = 1; i <= hall.getCols(); i++) {
            System.out.printf("%2d", i);
        }
        System.out.println();

        // 打印行和座位状态
        for (int row = 1; row <= hall.getRows(); row++) {
            System.out.printf("%2d ", row);
            for (int col = 1; col <= hall.getCols(); col++) {
                String seatId = hall.getId() + "_" + row + "_" + col;
                boolean sold = seats.stream().anyMatch(s -> s.getId().equals(seatId) && s.isSold());
                System.out.print(sold ? " X" : " O");
            }
            System.out.println();
        }

        System.out.print("请输入要购买的座位号(格式: 行号,列号，多个用逗号分隔): ");
        String seatInput = scanner.nextLine();
        String[] seatPairs = seatInput.split(",");

        List<String> seatIds = new java.util.ArrayList<>();
        for (String pair : seatPairs) {
            String[] parts = pair.trim().split(",");
            if (parts.length != 2) {
                System.out.println("座位格式错误: " + pair);
                return;
            }
            try {
                int row = Integer.parseInt(parts[0]);
                int col = Integer.parseInt(parts[1]);
                if (row < 1 || row > hall.getRows() || col < 1 || col > hall.getCols()) {
                    System.out.println("无效的座位: " + pair);
                    return;
                }
                seatIds.add(hall.getId() + "_" + row + "_" + col);
            } catch (NumberFormatException e) {
                System.out.println("座位格式错误: " + pair);
                return;
            }
        }

        System.out.print("请输入顾客手机号: ");
        String phone = scanner.nextLine();

        try {
            Ticket ticket = ((FrontDesk) currentUser).sellTicket(show, seatIds, phone);
            System.out.println("售票成功!");
            System.out.println("票号: " + ticket.getId());
            System.out.println("电影: " + show.getMovie().getName());
            System.out.println("放映时间: " + new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm").format(show.getShowTime()));
            System.out.println("放映厅: " + show.getHall().getName());
            System.out.println("座位: " + seatInput);
            System.out.println("总价: " + (ticket.getPrice() * seatIds.size()));
        } catch (IllegalArgumentException e) {
            System.out.println("售票失败: " + e.getMessage());
        }
    }

    private void refundTicket(Scanner scanner) {
        System.out.print("\n请输入要退的票号: ");
        String ticketId = scanner.nextLine();

        try {
            ((FrontDesk) currentUser).refundTicket(ticketId);
            System.out.println("退票成功");
        } catch (IllegalArgumentException e) {
            System.out.println("退票失败: " + e.getMessage());
        }
    }

    private int getValidInt(Scanner scanner, int min, int max) {
        while (true) {
            try {
                int num = Integer.parseInt(scanner.nextLine());
                if (num >= min && num <= max) return num;
                System.out.printf("请输入%d-%d之间的数字: ", min, max);
            } catch (NumberFormatException e) {
                System.out.print("输入无效，请重新输入: ");
            }
        }
    }

    private double getValidDouble(Scanner scanner, double min, double max) {
        while (true) {
            try {
                double num = Double.parseDouble(scanner.nextLine());
                if (num >= min && num <= max) return num;
                System.out.printf("请输入%.1f-%.1f之间的数字: ", min, max);
            } catch (NumberFormatException e) {
                System.out.print("输入无效，请重新输入: ");
            }
        }
    }
}
